package com.strong.utils.jpa.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.strong.utils.StrongUtils;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import java.lang.reflect.ParameterizedType;
import java.util.List;

/**
 * 自定义数据库处理Service的实现类.
 *
 * @param <E> 实体类泛型
 * @param <M> 模型类泛型
 * @author Simen
 * @version 1.0
 */
public abstract class StrongServiceImpl<E, M> implements StrongService<E, M> {

    /**
     * 类型类
     */
    private final ParameterizedType TYPE_CLASS = (ParameterizedType) this.getClass().getGenericSuperclass();

    /**
     * 实体类的class
     */
    private final Class<E> CLASS_E = (Class<E>) TYPE_CLASS.getActualTypeArguments()[0];

    /**
     * 模型类的class
     */
    private final Class<M> CLASS_M = (Class<M>) TYPE_CLASS.getActualTypeArguments()[1];

    @Autowired
    private PlatformTransactionManager transactionManager;

    @Override/////////
    public M getModel(@NotNull final E entity, final String... strsIncludeProperties) {
        return getModel(entity, true, strsIncludeProperties);
    }

    @Override
    public M getModel(@NotNull final E entity, @NotNull final boolean ignoreNullValue, final String... strsIncludeProperties) {
        if (ObjectUtil.isNull(entity)) {
            return null;
        } else {
            return BeanUtil.toBean(entity, CLASS_M, StrongUtils.getCopyOptionsInclude(strsIncludeProperties));
        }
    }

    @Override
    public List<M> getModelList(@NotEmpty final List<E> listE, @NotNull final boolean isIgnoreNullValue, final String... strsIncludeProperties) {
        if (CollUtil.isNotEmpty(listE)) {
            return BeanUtil.copyToList(listE, CLASS_M, StrongUtils.getCopyOptionsInclude(strsIncludeProperties));
        } else {
            return null;
        }
    }

    @Override
    public List<M> getModelList(@NotEmpty final List<E> listE, final String... strsIncludeProperties) {
        return getModelList(listE, true, strsIncludeProperties);
    }

    @Override
    public Page<M> getModelPage(@NotEmpty final Page<E> page, final String... strsIncludeProperties) {
        return getModelPage(page, true, strsIncludeProperties);
    }

    @Override
    public Page<M> getModelPage(@NotEmpty final Page<E> page, @NotNull final boolean isIgnoreNullValue, final String... strsIncludeProperties) {
        if (ObjectUtil.isNull(page)) {
            return new PageImpl<>(getModelList(page.getContent(), isIgnoreNullValue, strsIncludeProperties), page.getPageable(), page.getTotalElements());
        } else {
            return null;
        }
    }

    @Override
    public TransactionStatus getTransactionStatus() {
        DefaultTransactionDefinition transactionDefinition = new DefaultTransactionDefinition();
        transactionDefinition.setReadOnly(true);
        return transactionManager.getTransaction(transactionDefinition);
    }

}
